/**
 * Copyright 厦门中软海晟信息技术有限公司 版权所有 违者必究 2019
 */
package com.opencvjava.dtk;

import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Random;

import static com.opencvjava.support.util.CvUtils.imshow;
import static com.opencvjava.support.util.CvUtils.mat;
import static org.opencv.imgproc.Imgproc.COLOR_BGR2GRAY;
import static org.opencv.imgproc.Imgproc.THRESH_OTSU;
import static org.opencv.imgproc.Imgproc.bilateralFilter;
import static org.opencv.imgproc.Imgproc.circle;
import static org.opencv.imgproc.Imgproc.cvtColor;
import static org.opencv.imgproc.Imgproc.rectangle;
import static org.opencv.imgproc.Imgproc.threshold;

/**
 * @author : sunzb(sunzb@hsit.com.cn)
 * @date: 2019/1/23
 */
@Service
public class DtkTest3 {
    private final Logger logger = LoggerFactory.getLogger(DtkTest3.class);
    private Random random = new Random();
    public void test() {
        Mat src = mat("dtk", "SheetStand_zkz2.jpg");
        if (src.empty()) {
            throw new RuntimeException("图片读取失败");
        }
        imshow("源图", src);
        Mat copy = src.clone();
        Mat gray = new Mat();
        cvtColor(src, gray, COLOR_BGR2GRAY);
        imshow("灰度", gray);
        Mat filter = gray;
//        bilateralFilter(gray, filter, 0, 10, 5);
//        imshow("双边滤波", filter);

        int total = (int) filter.total();
        int cols = filter.cols();
        int rows = filter.rows();

        int kernelSize = 3;
        int kernelWidth = 7;

        int index, w, h, count, topCount, bottomCount, leftCount, rightCount;
        int tlRow = 0, tlCol = 0, brRow = 0, brCol = 0;
        boolean brColFind;
        Mat submat;
        Mat binary = new Mat();
        byte[] data;
        for (int row = 0; row < rows - kernelWidth; row++) {
            for (int col = 0; col < cols - kernelWidth; col++) {
                submat = filter.submat(new Rect(col, row, kernelWidth, kernelWidth));
                threshold(submat, binary, 127, 255, THRESH_OTSU);
                data = new byte[(int) submat.total()];
                binary.get(0, 0, data);
                count = 0;
                for (h = 0; h < kernelWidth; h++) {
                    for (w = 0; w < kernelWidth; w++) {
                        index = h * kernelWidth + w;
                        if (data[index] == 0) {
                            count++;
                        }
                    }
                }
                if (data[24] == 0) {
                    topCount = lineCount(data[3], data[10], data[17]);
                    bottomCount = lineCount(data[31], data[38], data[45]);
                    leftCount = lineCount(data[21], data[22], data[23]);
                    rightCount = lineCount(data[25], data[26], data[27]);
                    if (rightCount == 3 && bottomCount == 3 && topCount != 3  && leftCount != 3) {
                        brRow = 0;
                        brCol = 0;
                        tlRow = row;
                        tlCol = col;
                        count = -1;
                        brColFind = true;
                        ite:
                        for (int tempCol = tlCol; tempCol < cols - kernelWidth; tempCol++) {
                            submat = filter.submat(new Rect(tempCol, tlRow, kernelWidth, kernelWidth));
                            threshold(submat, binary, 127, 255, THRESH_OTSU);
                            data = new byte[(int) submat.total()];
                            binary.get(0, 0, data);
                            if (data[24] != 0) {
                                ++count;
                                if (count > (tempCol - tlCol) / 100) {
                                    brColFind = false;
                                    break ite;
                                }
                            }
                            for (h = 0; h < kernelWidth; h++) {
                                for (w = 0; w < kernelWidth; w++) {
                                    topCount = lineCount(data[3], data[10], data[17]);
                                    bottomCount = lineCount(data[31], data[38], data[45]);
                                    leftCount = lineCount(data[21], data[22], data[23]);
                                    rightCount = lineCount(data[25], data[26], data[27]);
                                    if (leftCount == 3 && bottomCount == 3 && topCount != 3 && rightCount != 3) {
                                        brCol = tempCol;
                                        break ite;
                                    }
                                }
                            }
                        }
                        if (brColFind) {
                            count = -1;
                            ite:
                            for (int rowTemp = tlRow; rowTemp < rows - kernelWidth; rowTemp++) {
                                submat = filter.submat(new Rect(tlCol, rowTemp, kernelWidth, kernelWidth));
                                threshold(submat, binary, 127, 255, THRESH_OTSU);
                                data = new byte[(int) submat.total()];
                                binary.get(0, 0, data);
                                if (data[24] != 0) {
                                    ++count;
                                    if (count > (rowTemp - tlRow) / 100) {
                                        break ite;
                                    }
                                }
                                for (h = 0; h < kernelWidth; h++) {
                                    for (w = 0; w < kernelWidth; w++) {
                                        topCount = lineCount(data[3], data[10], data[17]);
                                        bottomCount = lineCount(data[31], data[38], data[45]);
                                        leftCount = lineCount(data[21], data[22], data[23]);
                                        rightCount = lineCount(data[25], data[26], data[27]);
                                        if (topCount == 3 && rightCount == 3 && bottomCount != 3 && leftCount != 3) {
                                            brRow = rowTemp;
                                            break ite;
                                        }
                                    }
                                }
                            }
                        }
                        if (brCol != 0 && brRow != 0 && (brRow - tlRow) > 10 && (brCol - tlCol) > 10) {
                            rectangle(src, new Point(tlCol + 3, tlRow + 3), new Point(brCol + 3, brRow + 3),
                                    new Scalar(random.nextInt(256), random.nextInt(256), random.nextInt(256)),
                                    2, 8, 0);
                        }
                    }
                }
            }
        }
        imshow("角点", src);
    }

    private int lineCount(byte color1, byte color2, byte color3) {
        int count = 0;
        if (color1 == 0) count++;
        if (color2 == 0) count++;
        if (color3 == 0) count++;
        return count;
    }
}
